#!/usr/bin/env python
#-*- coding:utf-8 -*-

"""
    Aplica el concepto de mixin para definir atributos y gramatica comun.
        - Nombre: objetos que tienen un nombre.
        - Entrenamiento: objetos que tienen dos estados de entrenamiento.
        - Output: objetos que tienen un conjunto de salida.
            (ejemplo: un nodo de un arbol de grado N).
"""

class Nombre (object):
    """
        Define el atributo nombre: un string que define como se denomina a la instancia.
    """
    
    def __init__(self, nombre):
        self._nombre = nombre

    def get_nombre(self):
        """
            Obtiene el nombre de la instancia.
        """
        return self._nombre

    def set_nombre(self, nombre):
        """
            Modifica el nombre de la instancia.            
        """
        self._nombre = nombre

class Entrenamiento (object):
    """
        Agrega el atributo entrenamiento: provee una manera de diferenciar entrenamiento
            entre el estado de aceptar nueva informacion o simplemente procesar
            los datos nuevos sin modificar los conocimientos de una red.
    """
    
    def __init__(self, entrenamiento):
        self._entrenamiento = bool(entrenamiento)
    
    def get_entrenamiento(self):
        """
            Obtiene el estado de la bandera entrenamiento de la instancia.            
        """
        return self._entrenamiento

    def set_entrenamiento(self, entrenamiento):
        """
            Modifica el             
        """
        self._entrenamiento = bool(entrenamiento)


class Output (object):
    """
       Agrega el atributo outputs: un conjunto de enlaces de salida
        - El metodo foward_cast permite implementar flooding entre instancias de Output.
        - Las salidas no estan repetidas.
    """

    def __init__(self):
        self._outputs = set()

    def get_outputs(self):
        """
            Obtiene el conjunto de enlaces de salida.
        """
        return self._outputs

    def add_output(self, other):
        """
            Agrega al conjunto de enlaces de salida un nuevo elemento.
        """
        self._outputs.add(other)


    def foward_cast(self, origin, message):
        """
            Aplica el algoritmo flooding en el conjunto de enlaces salientes:
                - El mensaje se manda a todos los enlaces salientes.
                - El unico destino obviado es a uno mismo.
                - Si en la red existen caminos cerrados, es responsabilidad del 
                usuario asegurarse de que no se recorran.
        """
        for neighbour in self._outputs:
            if neighbour != origin:
                neighbour.foward_cast(self, message) 

if __name__ == '__main__':
    pass


